package base.json.fastjson.demo01;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 阿里巴巴的 fastjson 入门详解 http://kimmking.github.io/2017/06/06/json-best-practice/
 */
@Slf4j
public class Client {
    public static void main(String[] args) {

    }

    /**
     * 功能：Obj -> String
     */
    @Test
    public void testCase1(){
        User user = new User("张三",18, new BigDecimal("123456789.0123"));
        String s = JSON.toJSONString(user);
        //{"age":18,"name":"张三","salary":123456789.0123}
        System.out.println(s);

        String s1 = JSONObject.toJSONString(user);
        //{"age":18,"name":"张三","salary":123456789.0123}
        System.out.println(s1);
    }

    /**
     * 功能：String -> Obj
     */
    @Test
    public void testCase2(){
        // 单引号也是可以的，推荐用双引号
        String s = "{'age':18,'name':'张三','salary':123456789.0123}";
        User user = JSONObject.parseObject(s, User.class);
        //User(name=张三, age=18, salary=123456789.0123)
        System.out.println(user);
        System.out.println(user.getSalary());
    }

    /**
     * 功能：String  -> List
     */
    @Test
    public void testCase3(){
        String arrayString = "[{\"age\":18,\"name\":\"张三\",\"salary\":123456789.0123}]";
        List<User> users = JSONObject.parseArray(arrayString, User.class);
        //[User(name=张三, age=18, salary=123456789.0123)]
        System.out.println(users);
    }

    /**
     * 功能：Obj -> String 指定不同类型属性格式化器 更多参见：SerializerFeature 枚举
     *
     * 1、QuoteFieldNames, //key使用引号
     * 2、UseSingleQuotes, //使用单引号
     * 3、WriteMapNullValue, //输出Map的null值
     * 4、WriteEnumUsingToString, //枚举属性输出toString的结果
     * 5、WriteEnumUsingName, //枚举数据输出name
     * 6、UseISO8601DateFormat, //使用日期格式
     * 7、WriteNullListAsEmpty, //List为空则输出[]
     * 8、WriteNullStringAsEmpty, //String为空则输出””
     * 9、WriteNullNumberAsZero, //Number类型为空则输出0
     * 10、WriteNullBooleanAsFalse, //Boolean类型为空则输出false
     * 11、SkipTransientField, //@Transient注解标注的不输出
     * 12、SortField, //排序字段
     * 13、WriteTabAsSpecial,
     * 14、PrettyFormat, // 格式化JSON缩进
     * 15、WriteClassName, // 输出类名
     * 16、DisableCircularReferenceDetect, // 禁止循环引用
     * 17、WriteSlashAsSpecial, // 对斜杠’/’进行转义
     * 18、BrowserCompatible,
     * 19、WriteDateUseDateFormat, // 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
     *
     */
    @Test
    public void testCase4(){
        User user = new User("张三", 19, new BigDecimal("12345.5"), new Date());
        String s1 = JSONObject.toJSONString(user);
        //{"age":19,"birth":1632542318878,"name":"张三","salary":12345.5}
        System.out.println("s1----------->"+s1);

        String s2 = JSONObject.toJSONStringWithDateFormat(user, "yyyy-MM-dd HH:mm:ss", SerializerFeature.DisableCircularReferenceDetect);
        // {"age":19,"birth":"2021-09-25 12:35:57","name":"张三","salary":12345.5}
        System.out.println("s2---------->"+s2);

        String s3 = JSONObject.toJSONStringWithDateFormat(user, "yyyy/MM/dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat);
        // {"age":19,"birth":"2021-09-25 12:35:57","name":"张三","salary":12345.5}
        System.out.println("s3---------->"+s3);

        // 看User类日期属性上标注的注解
        User user1 = new User("张三", 19, new BigDecimal("12345.5"), new Date(), LocalDateTime.now());
        String s4 = JSONObject.toJSONString(user1);
        // {"age":19,"birth":1632546205634,"entry":"2021-09-25 13:03:25","name":"张三","salary":12345.5}
        System.out.println("s4---------->"+s4);

        User user2 = new User("张三", Sex.Male);
        String s5 = JSON.toJSONString(user2, SerializerFeature.WriteEnumUsingToString);
        log.info("s5--------->{}",s5);//s5--------->{"name":"张三","sex":"男"}
        String s6 = JSON.toJSONString(user2, SerializerFeature.UseSingleQuotes, SerializerFeature.WriteEnumUsingName);
        log.info("s6--------->{}",s6);//s6--------->{'name':'张三','sex':'Male'}
        String s7 = JSON.toJSONString(user2, SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString, SerializerFeature.WriteClassName);
        log.info("s7--------->{}",s7);//s7--------->{"@type":"base.json.fastjson.demo01.User","name":"张三","sex":"男"}

        //        JSON.writeJSONString(Writer, Object, SerializerFeature);
    }

    /**
     * 结论：
     * User 日期属性字段上标注序列化注解：@JSONField(format = "yyyy-MM-dd HH:mm:ss")，这种日期格式字符串会自动被fastjson反序列化成日期对象属性，反序列化能够自动识别如下日期格式：
     * ISO-8601日期格式
     * yyyy-MM-dd
     * yyyy-MM-dd HH:mm:ss
     * yyyy-MM-dd HH:mm:ss.SSS
     * 毫秒数字
     * 毫秒数字字符串
     * .NET JSON日期格式
     * new Date(198293238)
     * 为了防止fastjson在序列化和反序列化日期时出现错误，可以在字段属性上标记注解即可。
     */
    @Test
    public void testCase5(){
        //修改全局默认日期格式
        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
        String haha = JSON.toJSONString(new User("haha", 11, new BigDecimal("123"), new Date(), LocalDateTime.now()), SerializerFeature.WriteDateUseDateFormat);
        log.info("---------->{}",haha);//{"age":11,"birth":"2021-09-25","entry":"2021-09-25 17:34:44","name":"haha","salary":123}

        /**
         * 序列化
         */
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("李四",20,new BigDecimal("12345.6"),new Date(), LocalDateTime.now()));
        list.add(new User("王五",21,new BigDecimal("12345.7"),new Date(), LocalDateTime.now()));
        list.add(new User("赵六",22,new BigDecimal("12345.8"),new Date(), LocalDateTime.now()));

        String s1 = JSON.toJSONString(list);
        /*
         * [{"age":20,"birth":1632561548756,"entry":"2021-09-25 17:19:08","name":"李四","salary":12345.6},
         *  {"age":21,"birth":1632561548804,"entry":"2021-09-25 17:19:08","name":"王五","salary":12345.7},
         *  {"age":22,"birth":1632561548804,"entry":"2021-09-25 17:19:08","name":"赵六","salary":12345.8}
         * ]
         */
        log.info("s1----->{}",s1);

        /**
         * 反序列化
         */
        List list1 = JSON.parseObject(s1, List.class);
        log.info("list1--------->{}",list1.size());//3
        log.info("list1.0------------>{}", list1.get(0));//{"entry":"2021-09-25 17:19:08","name":"李四","birth":1632561548756,"salary":12345.6,"age":20}

        /**
         * 带泛型的反序列化
         */
        ArrayList<User> list3 = JSON.parseObject(s1, new TypeReference<ArrayList<User>>() {});
        log.info("list3--------->{}",list3.size());//3
        //User(name=李四, age=20, salary=12345.6, sex=null, birth=Sat Sep 25 17:08:30 CST 2021, entry=2021-09-25T17:08:30)
        log.info("list3.0------------>{}", list3.get(0));

        List<User> list2 = JSON.parseArray(s1, User.class);
        log.info("list2----------->{}",list2.size());//3
        //User(name=李四, age=20, salary=12345.6, sex=null, birth=Sat Sep 25 16:58:59 CST 2021, entry=2021-09-25T16:58:59)
        log.info("list2.0------------>{}", list2.get(0));
    }


}
